package com.example.selflearning.service.ehcache;
import com.example.selflearning.entity.UserEntity;
import lombok.extern.slf4j.Slf4j;
import org.ehcache.UserManagedCache;
import org.ehcache.config.builders.UserManagedCacheBuilder;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
/**
 * Created by yangjingzhi on 2019/5/20.
 */
@Slf4j
public class SyncCacheAsideUserService {
    private UserManagedCache<String, UserEntity> cache;
    private final ReentrantLock lock = new ReentrantLock();

    public SyncCacheAsideUserService() {
        cache = UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, UserEntity.class).build(true);
    }

    public UserEntity findUser(String id) {
        UserEntity userEntity = cache.get(id);
        if (userEntity == null) {
            lock.lock();
            userEntity = cache.get(id);
            if (userEntity == null) {
                userEntity = new UserEntity(id, "info ..."); // find user
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
                log.info("get user from db:{} ", id);
                cache.put(id, userEntity);
            } else {
                log.info("get user from cache after competition: {}", id);
            }
            log.info("get user from cache");
            lock.unlock();
        } else {
            log.info("get user from cache: {}", id);
        }
        return userEntity;
    }

    public static void main(String[] args) {
        final SyncCacheAsideUserService service = new SyncCacheAsideUserService();
        ExecutorService executorService = Executors.newFixedThreadPool(30);
        for (int i = 0; i < 10; i++) {
            executorService.execute(new Runnable() {
                public void run() {
                    service.findUser("1");
                }
            });
            executorService.execute(new Runnable() {
                public void run() {
                    service.findUser("2");
                }
            });
            executorService.execute(new Runnable() {
                public void run() {
                    service.findUser("3");
                }
            });
        }
        executorService.shutdown();
    }
}
